﻿using System;
using System.Reflection;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using NHibernate;
using NHibernate.Criterion;

namespace NMA.Infrastructure.NHibernate.Repository
{
    using NMA.Domain.Model;
    using NMA.Infrastructure.Logging;
    using NMA.Infrastructure.NHibernate.Container;
    using NMA.Infrastructure.NHibernate.UnitOfWork;    
    using NMA.Infrastructure.NHibernate.DomainObject;
    using NMA.Infrastructure.DBC;
    using NMA.Domain.Model.Repository;
    using NMA.Domain.Shared.Paging;    

    public class PollRepository : BaseRepository<IPoll>, IPollRepository
    {
        #region variables

        protected IUnitOfWorkFactory UnitOfWorkFactory { get; private set; }

        private static readonly ILog _logger = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);

        #endregion

        #region contructors

        public PollRepository() : this(IoC.GetInstance<IUnitOfWorkFactory>())
        { }

        public PollRepository(IUnitOfWorkFactory unitOfWorkFactory)
        {
            UnitOfWorkFactory = unitOfWorkFactory;
        }

        #endregion

        #region implement functions

        public IEnumerable<IPoll> All()
        {
            using (var uow = UnitOfWorkFactory.GetNewUnitOfWork())
            {
                ICriteria critreria = uow.Session.CreateCriteria<Poll>();
                uow.Commit();
                return critreria.List<Poll>();
            }
        }

        public int CountAllPoll()
        {            
            int result = 0;

            using (var uow = UnitOfWorkFactory.GetNewUnitOfWork())
            {
                // create criteria for this condition
                ICriteria criteria = uow.Session.CreateCriteria(typeof(IPoll));
                // set projection to row count
                criteria.SetProjection(Projections.RowCount());
                // get result from criteria
                result = criteria.UniqueResult<int>();
                uow.Commit();
            }

            return result;            
        }        

        public IPoll GetById(System.Guid id)
        {            
            IPoll poll = null;

            using (var uow = UnitOfWorkFactory.GetNewUnitOfWork())
            {
                poll = uow.Session.Get<Poll>(id);
                uow.Commit();
            }

            return poll;            
        }       

        public Guid Add(IPoll entity)
        {            
            object result = null;

            using (var uow = UnitOfWorkFactory.GetNewUnitOfWork())
            {
                result = uow.Session.Save(entity);

                uow.Session.Flush();
                uow.Session.Clear();

                uow.Commit();
            }

            return (Guid)result;            
        }

        public void Remove(IPoll entity)
        {            
            using (var uow = UnitOfWorkFactory.GetNewUnitOfWork())
            {
                uow.Session.Delete(entity);
                uow.Commit();
            }            
        }

        public void Update(IPoll entity)
        {            
            using (var uow = UnitOfWorkFactory.GetNewUnitOfWork())
            {
                uow.Session.Update(entity);
                uow.Commit();
            }            
        }

        public IEnumerable<IPoll> GetBy(Expression<System.Func<IPoll, bool>> condition)
        {            
            IEnumerable<IPoll> result = null;
            IList<IPoll> listOfNews = null;

            using (var uow = UnitOfWorkFactory.GetNewUnitOfWork())
            {
                // creating criteria for this condition
                ICriteria criteria = uow.Session.CreateCriteria(typeof(IPoll));
                // getting result from criteria
                listOfNews = criteria.List<IPoll>();

                if (listOfNews == null)
                    throw new Exception("List of poll is null");                    

                result = listOfNews.Where<IPoll>(condition.Compile());
            }

            return result;            
        }

        public IPagedList<IPoll> All(int pageIndex, int pageSize)
        {
            using (var uow = UnitOfWorkFactory.GetNewUnitOfWork())
            {
                var criteria = uow.Session.CreateCriteria(typeof(Poll));

                return PagedList(criteria, pageIndex, pageSize);
            }
        }

        #endregion
    }
}